home *** CD-ROM | disk | FTP | other *** search
/ CD Actual 85 / CD Temático 40 Febrero 2004.iso / DOS / ntfs / common / inode.c < prev    next >
Encoding:
C/C++ Source or Header  |  2001-02-11  |  33.4 KB  |  1,321 lines

  1. /*
  2.  *  inode.c
  3.  *
  4.  *  Copyright (C) 1995-1999 Martin von L÷wis
  5.  *  Copyright (C) 1996 Albert D. Cahalan
  6.  *  Copyright (C) 1996-1997 RΘgis Duchesne
  7.  *  Copyright (C) 1998 Joseph Malicki
  8.  *  Copyright (C) 1999 Steve Dodd
  9.  */
  10.  
  11. #include "ntfstypes.h"
  12. #include "ntfsendian.h"
  13. #include "struct.h"
  14. #include "inode.h"
  15.  
  16. #include <errno.h>
  17. #ifdef HAVE_STRING_H
  18. #include <string.h>
  19. #endif
  20. #include "macros.h"
  21. #include "attr.h"
  22. #include "super.h"
  23. #include "dir.h"
  24. #include "support.h"
  25. #include "util.h"
  26.  
  27. typedef struct {
  28.     int recno;
  29.     unsigned char* record;
  30. } ntfs_mft_record;
  31.  
  32. typedef struct {
  33.     int size;
  34.     int count;
  35.     ntfs_mft_record* records;
  36. } ntfs_disk_inode;
  37.  
  38. void
  39. ntfs_fill_mft_header(ntfs_u8*mft,int record_size,int blocksize,
  40.         int sequence_number)
  41. {
  42.     int fixup_count = record_size / blocksize + 1;
  43.     int attr_offset = (0x2a + (2 * fixup_count) + 7) & ~7;
  44.     int fixup_offset = 0x2a;
  45.  
  46.     NTFS_PUTU32(mft + 0x00, 0x454c4946);         /* FILE */
  47.     NTFS_PUTU16(mft + 0x04, 0x2a);               /* offset to fixup */
  48.     NTFS_PUTU16(mft + 0x06, fixup_count);        /* Number of fixups */
  49.     NTFS_PUTU16(mft + 0x10, sequence_number);
  50.     NTFS_PUTU16(mft + 0x12, 1);                  /* hard link count */
  51.     NTFS_PUTU16(mft + 0x14, attr_offset);        /* Offset to attributes */
  52.     NTFS_PUTU16(mft + 0x16, 1);                  /*FIXME: flags ?? */
  53.     NTFS_PUTU32(mft + 0x18, attr_offset + 0x08);    /* In use */
  54.     NTFS_PUTU32(mft + 0x1c, record_size);        /* Total size */
  55.  
  56.     NTFS_PUTU16(mft + fixup_offset, 1);             /* Fixup word */
  57.     NTFS_PUTU32(mft + attr_offset, 0xffffffff);     /* End marker */
  58. }
  59.  
  60. /* Search in an inode an attribute by type and name */
  61. ntfs_attribute* 
  62. ntfs_find_attr(ntfs_inode *ino,int type,char *name)
  63. {
  64.     int i;
  65.     if(!ino){
  66.         ntfs_error("ntfs_find_attr: NO INODE!\n");
  67.         return 0;
  68.     }
  69.     for(i=0;i<ino->attr_count;i++)
  70.     {
  71.         if(type==ino->attrs[i].type)
  72.         {
  73.             if(!name && !ino->attrs[i].name)
  74.                 return ino->attrs+i;
  75.             if(name && !ino->attrs[i].name)
  76.                 return 0;
  77.             if(!name && ino->attrs[i].name)
  78.                 return 0;
  79.             if(ntfs_ua_strncmp(ino->attrs[i].name,name,strlen(name))==0)
  80.                 return ino->attrs+i;
  81.         }
  82.         if(type<ino->attrs[i].type)
  83.             return 0;
  84.     }
  85.     return 0;
  86. }
  87.  
  88. /* FIXME: need better strategy to extend the MFT */
  89. static int 
  90. ntfs_extend_mft(ntfs_volume *vol)
  91. {
  92.     /* Try to allocate at least 0.1% of the remaining disk space
  93.        for inodes. If the disk is almost full, make sure at least one
  94.        inode is requested.
  95.      */
  96.     int size,rcount,error,block;
  97.     ntfs_attribute* mdata,*bmp;
  98.     ntfs_u8 *buf;
  99.     ntfs_io io;
  100.  
  101.     mdata=ntfs_find_attr(vol->mft_ino,vol->at_data,0);
  102.     /* first check whether there is uninitialized space */
  103.     if(mdata->allocated<mdata->size+vol->mft_recordsize){
  104.         size=ntfs_get_free_cluster_count(vol->bitmap)*vol->clustersize;
  105.         block=vol->mft_recordsize;
  106.         size=max(size/1000,mdata->size+vol->mft_recordsize);
  107.         size=((size+block-1)/block)*block;
  108.         /* require this to be a single chunk */
  109.         error=ntfs_extend_attr(vol->mft_ino,mdata,&size,
  110.                        ALLOC_REQUIRE_SIZE);
  111.         /* Try again, now we have the largest available fragment */
  112.         if(error==ENOSPC){
  113.             /* round down to multiple of mft record size */
  114.             size=(size/vol->mft_recordsize)*vol->mft_recordsize;
  115.             if(!size)return ENOSPC;
  116.             error=ntfs_extend_attr(vol->mft_ino,mdata,&size,
  117.                            ALLOC_REQUIRE_SIZE);
  118.         }
  119.         if(error)
  120.             return error;
  121.     }
  122.     /* even though we might have allocated more than needed,
  123.        we initialize only one record */
  124.     mdata->size+=vol->mft_recordsize;
  125.     
  126.     /* now extend the bitmap if necessary*/
  127.     rcount=mdata->size/vol->mft_recordsize;
  128.     bmp=ntfs_find_attr(vol->mft_ino,vol->at_bitmap,0);
  129.     if(bmp->size*8<rcount){ /* less bits than MFT records */
  130.         ntfs_u8 buf[1];
  131.         /* extend bitmap by one byte */
  132.         error=ntfs_resize_attr(vol->mft_ino,bmp,bmp->size+1);
  133.         if(error)return error;
  134.         /* write the single byte */
  135.         buf[0]=0;
  136.         io.fn_put=ntfs_put;
  137.         io.fn_get=ntfs_get;
  138.         io.param=buf;
  139.         io.size=1;
  140.         error=ntfs_write_attr(vol->mft_ino,vol->at_bitmap,0,
  141.                       bmp->size-1,&io);
  142.         if(error)return error;
  143.         if(io.size!=1)return EIO;
  144.     }
  145.  
  146.     /* now fill in the MFT header for the new block */
  147.     buf=ntfs_calloc(vol->mft_recordsize);
  148.     if(!buf)return ENOMEM;
  149.     ntfs_fill_mft_header(buf,vol->mft_recordsize,vol->blocksize,0);
  150.     ntfs_insert_fixups(buf,vol->blocksize);
  151.     io.param=buf;
  152.     io.size=vol->mft_recordsize;
  153.     error=ntfs_write_attr(vol->mft_ino,vol->at_data,0,
  154.                   (rcount-1)*vol->mft_recordsize,&io);
  155.     if(error)return error;
  156.     if(io.size!=vol->mft_recordsize)return EIO;
  157.     error=ntfs_update_inode(vol->mft_ino);
  158.     if(error)return error;
  159.     return 0;
  160. }
  161.  
  162. /* Insert all attributes from the record mftno of the MFT in the inode ino */
  163. void ntfs_insert_mft_attributes(ntfs_inode* ino,char *mft,int mftno)
  164. {
  165.     int i;
  166.     char *it;
  167.     int type,len;
  168.     /* check for duplicate */
  169.     for(i=0;i<ino->record_count;i++)
  170.         if(ino->records[i]==mftno)
  171.             return;
  172.     /* (re-)allocate space if necessary */
  173.     if(ino->record_count % 8==0)
  174.     {
  175.         int *new;
  176.         new = ntfs_malloc((ino->record_count+8)*sizeof(int));
  177.         if( !new )
  178.             return;
  179.         if( ino->records ) {
  180.             for(i=0;i<ino->record_count;i++)
  181.                 new[i] = ino->records[i];
  182.             ntfs_free( ino->records );
  183.         }
  184.         ino->records = new;
  185.     }
  186.     ino->records[ino->record_count]=mftno;
  187.     ino->record_count++;
  188.     it = mft + NTFS_GETU16(mft + 0x14);
  189.     do{
  190.         type=NTFS_GETU32(it);
  191.         len=NTFS_GETU32(it+4);
  192.         if(type!=-1) {
  193.             /* FIXME: check ntfs_insert_attribute for failure (e.g. no mem)? */
  194.             ntfs_insert_attribute(ino,it);
  195.         }
  196.         it+=len;
  197.     }while(type!=-1); /* attribute list ends with type -1 */
  198. }
  199.  
  200. /* Read and insert all the attributes of an 'attribute list' attribute
  201.    Return the number of remaining bytes in *plen
  202. */
  203. static int parse_attributes(ntfs_inode *ino, ntfs_u8 *alist, int *plen)
  204. {
  205.     char *mft;
  206.     int mftno,l,error;
  207.     int last_mft=-1;
  208.     int len=*plen;
  209.     mft=ntfs_malloc(ino->vol->mft_recordsize);
  210.     if( !mft )
  211.         return ENOMEM;
  212.     while(len>8)
  213.     {
  214.         l=NTFS_GETU16(alist+4);
  215.         if(l>len)break;
  216.         /* process an attribute description */
  217.         mftno=NTFS_GETU32(alist+0x10); /* BUG: this is u64 */
  218.         if(mftno!=last_mft){
  219.             last_mft=mftno;
  220.             /* FIXME: avoid loading record if it's 
  221.                already processed */
  222.             error=ntfs_read_mft_record(ino->vol,mftno,mft);
  223.             if(error)return error;
  224.             ntfs_insert_mft_attributes(ino,mft,mftno);
  225.         }
  226.         len-=l;
  227.         alist+=l;
  228.     }
  229.     ntfs_free(mft);
  230.     *plen=len;
  231.     return 0;
  232. }
  233.  
  234. static void ntfs_load_attributes(ntfs_inode* ino)
  235. {
  236.     ntfs_attribute *alist;
  237.     int datasize;
  238.     int offset,len,delta;
  239.     char *buf;
  240.     ntfs_volume *vol=ino->vol;
  241.     ntfs_debug(DEBUG_FILE2, "load_attributes %x 1\n",ino->i_number);
  242.     ntfs_insert_mft_attributes(ino,ino->attr,ino->i_number);
  243.     ntfs_debug(DEBUG_FILE2, "load_attributes %x 2\n",ino->i_number);
  244.     alist=ntfs_find_attr(ino,vol->at_attribute_list,0);
  245.     ntfs_debug(DEBUG_FILE2, "load_attributes %x 3\n",ino->i_number);
  246.     if(!alist)
  247.         return;
  248.     ntfs_debug(DEBUG_FILE2, "load_attributes %x 4\n",ino->i_number);
  249.     datasize=alist->size;
  250.     if(alist->resident)
  251.     {
  252.         parse_attributes(ino,alist->d.data,&datasize);
  253.         return;
  254.     }
  255.     buf=ntfs_malloc(1024);
  256.     if( !buf )
  257.         return;
  258.     delta=0;
  259.     for(offset=0;datasize;datasize-=len)
  260.     {
  261.         ntfs_io io;
  262.         io.fn_put=ntfs_put;
  263.         io.fn_get=0;
  264.         io.param=buf+delta;
  265.         io.size=len=min(datasize,1024-delta);
  266.         if(ntfs_read_attr(ino,vol->at_attribute_list,0,offset,&io)){
  267.             ntfs_error("error in load_attributes\n");
  268.         }
  269.         delta=len;
  270.         parse_attributes(ino,buf,&delta);
  271.         if(delta)
  272.             /* move remaining bytes to buffer start */
  273.             ntfs_memmove(buf,buf+len-delta,delta);
  274.     }
  275.     ntfs_debug(DEBUG_FILE2, "load_attributes %x 5\n",ino->i_number);
  276.     ntfs_free(buf);
  277. }
  278.     
  279. int ntfs_init_inode(ntfs_inode *ino,ntfs_volume *vol,int inum)
  280. {
  281.     char *buf;
  282.     int error;
  283.  
  284.     ntfs_debug(DEBUG_FILE1, "Initializing inode %x\n",inum);
  285.     if(!vol)
  286.         ntfs_error("NO VOLUME!\n");
  287.     ino->i_number=inum;
  288.     ino->vol=vol;
  289.     ino->attr=buf=ntfs_malloc(vol->mft_recordsize);
  290.     if( !buf )
  291.         return ENOMEM;
  292.     error=ntfs_read_mft_record(vol,inum,ino->attr);
  293.     if(error){
  294.         ntfs_debug(DEBUG_OTHER, "init inode: %x failed\n",inum);
  295.         return error;
  296.     }
  297.     ntfs_debug(DEBUG_FILE2, "Init: got mft %x\n",inum);
  298.     ino->sequence_number=NTFS_GETU16(buf+0x10);
  299.     ino->attr_count=0;
  300.     ino->record_count=0;
  301.     ino->records=0;
  302.     ino->attrs=0;
  303.     ntfs_load_attributes(ino);
  304.     ntfs_debug(DEBUG_FILE2, "Init: done %x\n",inum);
  305.     return 0;
  306. }
  307.  
  308. void ntfs_clear_inode(ntfs_inode *ino)
  309. {
  310.     int i;
  311.     if(!ino->attr){
  312.         ntfs_error("ntfs_clear_inode: double free\n");
  313.         return;
  314.     }
  315.     ntfs_free(ino->attr);
  316.     ino->attr=0;
  317.     ntfs_free(ino->records);
  318.     ino->records=0;
  319.     for(i=0;i<ino->attr_count;i++)
  320.     {
  321.         if(ino->attrs[i].name)
  322.             ntfs_free(ino->attrs[i].name);
  323.         if(ino->attrs[i].resident)
  324.         {
  325.             if(ino->attrs[i].d.data)
  326.                 ntfs_free(ino->attrs[i].d.data);
  327.         }else{
  328.             if(ino->attrs[i].d.r.runlist)
  329.                 ntfs_free(ino->attrs[i].d.r.runlist);
  330.         }
  331.     }
  332.     ntfs_free(ino->attrs);
  333.     ino->attrs=0;
  334. }
  335.  
  336. /* Check and fixup a MFT record */
  337. int ntfs_check_mft_record(ntfs_volume *vol,char *record)
  338. {
  339.     return ntfs_fixup_record(vol, record, "FILE", vol->mft_recordsize);
  340. }
  341.  
  342. /* Return (in result) the value indicating the next available attribute 
  343.    chunk number. Works for inodes w/o extension records only */
  344. int ntfs_allocate_attr_number(ntfs_inode *ino, int *result)
  345. {
  346.     if(ino->record_count!=1)
  347.         return EOPNOTSUPP;
  348.     *result=NTFS_GETU16(ino->attr+0x28);
  349.     NTFS_PUTU16(ino->attr+0x28, (*result)+1);
  350.     return 0;
  351. }
  352.  
  353. /* find the location of an attribute in the inode. A name of NULL indicates
  354.    unnamed attributes. Return pointer to attribute or NULL if not found */
  355. char *
  356. ntfs_get_attr(ntfs_inode *ino,int attr,char *name)
  357. {
  358.     /* location of first attribute */
  359.     char *it= ino->attr + NTFS_GETU16(ino->attr + 0x14);
  360.     int type;
  361.     int len;
  362.     /* Only check for magic DWORD here, fixup should have happened before */
  363.     if(!IS_MFT_RECORD(ino->attr))return 0;
  364.     do{
  365.         type=NTFS_GETU32(it);
  366.         len=NTFS_GETU16(it+4);
  367.         /* We found the attribute type. Is the name correct, too? */
  368.         if(type==attr)
  369.         {
  370.             int namelen=NTFS_GETU8(it+9);
  371.             char *name_it;
  372.             /* match given name and attribute name if present,
  373.                make sure attribute name is Unicode */
  374.             for(name_it=it+NTFS_GETU16(it+10);namelen;
  375.                 name++,name_it+=2,namelen--)
  376.                 if(*name_it!=*name || name_it[1])break;
  377.             if(!namelen)break;
  378.         }
  379.         it+=len;
  380.     }while(type!=-1); /* attribute list end with type -1 */
  381.     if(type==-1)return 0;
  382.     return it;
  383. }
  384.  
  385. int 
  386. ntfs_get_attr_size(ntfs_inode*ino,int type,char*name)
  387. {
  388.     ntfs_attribute *attr=ntfs_find_attr(ino,type,name);
  389.     if(!attr)return 0;
  390.     return attr->size;
  391. }
  392.     
  393. int 
  394. ntfs_attr_is_resident(ntfs_inode*ino,int type,char*name)
  395. {
  396.     ntfs_attribute *attr=ntfs_find_attr(ino,type,name);
  397.     if(!attr)return 0;
  398.     return attr->resident;
  399. }
  400.     
  401. /*
  402.  * A run is coded as a type indicator, an unsigned length, and a signed cluster
  403.  * offset.
  404.  * . To save space, length and offset are fields of variable length. The low
  405.  *   nibble of the type indicates the width of the length :), the high nibble
  406.  *   the width of the offset.
  407.  * . The first offset is relative to cluster 0, later offsets are relative to
  408.  *   the previous cluster.
  409.  *
  410.  * This function decodes a run. Length is an output parameter, data and cluster
  411.  * are in/out parameters.
  412.  */
  413. int ntfs_decompress_run(unsigned char **data, int *length, ntfs_cluster_t *cluster,
  414.     int *ctype)
  415. {
  416.     unsigned char type=*(*data)++;
  417.     *ctype=0;
  418.     switch(type & 0xF)
  419.     {
  420.     case 1: *length=NTFS_GETU8(*data);break;
  421.     case 2: *length=NTFS_GETU16(*data);break;
  422.     case 3: *length=NTFS_GETU24(*data);break;
  423.     case 4: *length=NTFS_GETU32(*data);break;
  424.         /* Note: cases 5-8 are probably pointless to code,
  425.            since how many runs > 4GB of length are there?
  426.            at the most, cases 5 and 6 are probably necessary,
  427.            and would also require making length 64-bit
  428.            throughout */
  429.     default:
  430.         ntfs_error("Can't decode run type field %x\n",type);
  431.         return -1;
  432.     }
  433.     *data+=(type & 0xF);
  434.  
  435.     switch(type & 0xF0)
  436.     {
  437.     case 0:    *ctype=2; break;
  438.     case 0x10: *cluster += NTFS_GETS8(*data);break;
  439.     case 0x20: *cluster += NTFS_GETS16(*data);break;
  440.     case 0x30: *cluster += NTFS_GETS24(*data);break;
  441.     case 0x40: *cluster += NTFS_GETS32(*data);break;
  442. #if 0 /* Keep for future, in case ntfs_cluster_t ever becomes 64bit */
  443.     case 0x50: *cluster += NTFS_GETS40(*data);break;
  444.     case 0x60: *cluster += NTFS_GETS48(*data);break;
  445.     case 0x70: *cluster += NTFS_GETS56(*data);break;
  446.     case 0x80: *cluster += NTFS_GETS64(*data);break;        
  447. #endif
  448.     default:
  449.         ntfs_error("Can't decode run type field %x\n",type);
  450.         return -1;
  451.     }
  452.     *data+=(type >> 4);
  453.     return 0;
  454. }
  455.  
  456. /* Reads l bytes of the attribute (attr,name) of ino starting at offset
  457.    on vol into buf. Returns the number of bytes read in the ntfs_io struct.
  458.    Returns 0 on success, errno on failure */
  459. int ntfs_readwrite_attr(ntfs_inode *ino, ntfs_attribute *attr, int offset,
  460.     ntfs_io *dest)
  461. {
  462.     int rnum;
  463.     ntfs_cluster_t cluster,s_cluster,vcn,len;
  464.     int l,chunk,copied;
  465.     int s_vcn;
  466.     int clustersize;
  467.     int error;
  468.  
  469.     clustersize=ino->vol->clustersize;
  470.     l=dest->size;
  471.     if(l==0)
  472.         return 0;
  473.     if(dest->do_read)
  474.     {
  475.         /* if read _starts_ beyond end of stream, return nothing */
  476.         if(offset>=attr->size){
  477.             dest->size=0;
  478.             return 0;
  479.         }
  480.  
  481.         /* if read _extends_ beyond end of stream, return as much
  482.             initialised data as we have */
  483.         if(offset+l>=attr->size) 
  484.             l=dest->size=attr->size-offset;
  485.  
  486.     }else {
  487.         /* fixed by CSA: if writing beyond end, extend attribute */
  488.  
  489.         /* if write extends beyond _allocated_ size, extend attrib */
  490.         if (offset+l>attr->allocated) {
  491.             error=ntfs_resize_attr(ino,attr,offset+l);
  492.             if(error)
  493.                 return error;
  494.         }
  495.  
  496.         /* the amount of initialised data has increased; update */
  497.         /* FIXME: shouldn't we zero-out the section between the old
  498.             initialised length and the write start? */
  499.         if (offset+l > attr->initialized) {
  500.             attr->initialized = offset+l;
  501.             attr->size = offset+l;
  502.         }
  503.     }
  504.     if(attr->resident)
  505.     {
  506.         if(dest->do_read)
  507.             dest->fn_put(dest,(ntfs_u8*)attr->d.data+offset,l);
  508.         else
  509.             dest->fn_get((ntfs_u8*)attr->d.data+offset,dest,l);
  510.         dest->size=l;
  511.         return 0;
  512.     }
  513.     /* read uninitialized data */
  514.     if(offset>=attr->initialized && dest->do_read)
  515.         return ntfs_read_zero(dest,l);
  516.     if(offset+l>attr->initialized && dest->do_read)
  517.     {
  518.         dest->size = chunk = offset+l - attr->initialized;
  519.         error = ntfs_readwrite_attr(ino,attr,offset,dest);
  520.         if(error)
  521.             return error;           
  522.         return ntfs_read_zero(dest,l-chunk);
  523.     }
  524.     if(attr->compressed){
  525.         if(dest->do_read)
  526.             return ntfs_read_compressed(ino,attr,offset,dest);
  527.         else
  528.             return ntfs_write_compressed(ino,attr,offset,dest);
  529.     }
  530.     vcn=0;
  531.     s_vcn = offset/clustersize;
  532.     for(rnum=0;rnum<attr->d.r.len && 
  533.             vcn+attr->d.r.runlist[rnum].len<=s_vcn;rnum++)
  534.         vcn+=attr->d.r.runlist[rnum].len;
  535.     if(rnum==attr->d.r.len)
  536.         /*FIXME: should extend runlist */
  537.         return EOPNOTSUPP;
  538.     
  539.     copied=0;
  540.     while(l)
  541.     {
  542.         s_vcn = offset/clustersize;
  543.         cluster=attr->d.r.runlist[rnum].cluster;
  544.         len=attr->d.r.runlist[rnum].len;
  545.  
  546.         s_cluster = cluster+s_vcn-vcn;
  547.             
  548.         chunk=min((vcn+len)*clustersize-offset,l);
  549.         dest->size=chunk;
  550.         error=ntfs_getput_clusters(ino->vol,s_cluster,
  551.                        offset-s_vcn*clustersize,dest);
  552.         if(error)/* FIXME: maybe return failure */
  553.         {
  554.             ntfs_error("Read error\n");
  555.             dest->size=copied;
  556.             return 0;
  557.         }
  558.         l-=chunk;
  559.         copied+=chunk;
  560.         offset+=chunk;
  561.         if(l && offset>=((vcn+len)*clustersize))
  562.         {
  563.             rnum++;
  564.             vcn+=len;
  565.             cluster = attr->d.r.runlist[rnum].cluster;
  566.             len = attr->d.r.runlist[rnum].len;
  567.         }
  568.     }
  569.     dest->size=copied;
  570.     return 0;
  571. }
  572.  
  573. int ntfs_read_attr(ntfs_inode *ino, int type, char *name, int offset,
  574.     ntfs_io *buf)
  575. {
  576.     ntfs_attribute *attr;
  577.     buf->do_read=1;
  578.     attr=ntfs_find_attr(ino,type,name);
  579.     if(!attr)
  580.         return EINVAL;
  581.     return ntfs_readwrite_attr(ino,attr,offset,buf);
  582. }
  583.  
  584. int ntfs_write_attr(ntfs_inode *ino, int type, char *name, int offset,
  585.         ntfs_io *buf)
  586. {
  587.     ntfs_attribute *attr;
  588.     buf->do_read=0;
  589.     attr=ntfs_find_attr(ino,type,name);
  590.     if(!attr)
  591.         return EINVAL;
  592.     return ntfs_readwrite_attr(ino,attr,offset,buf);
  593. }
  594.  
  595. int ntfs_vcn_to_lcn(ntfs_inode *ino,int vcn)
  596. {
  597.     int rnum;
  598.     ntfs_attribute *data;
  599.     data=ntfs_find_attr(ino,ino->vol->at_data,0);
  600.     /* It's hard to give an error code */
  601.     if(!data)return -1;
  602.     if(data->resident)return -1;
  603.     if(data->compressed)return -1;
  604.     if(data->size <= vcn*ino->vol->clustersize)return -1;
  605.  
  606.  
  607.     /* For Linux, block number 0 represents a hole.
  608.        Hopefully, nobody will attempt to bmap $Boot. */
  609.     if(data->initialized <= vcn*ino->vol->clustersize)
  610.         return 0;
  611.  
  612.     for(rnum=0;rnum<data->d.r.len && 
  613.             vcn>data->d.r.runlist[rnum].len;rnum++)
  614.         vcn-=data->d.r.runlist[rnum].len;
  615.     
  616.     return data->d.r.runlist[rnum].cluster+vcn;
  617. }
  618.  
  619. static int 
  620. allocate_store(ntfs_volume *vol,ntfs_disk_inode *store,int count)
  621. {
  622.     int i;
  623.     if(store->count>count)
  624.         return 0;
  625.     if(store->size<count){
  626.         ntfs_mft_record* n=ntfs_malloc((count+4)*sizeof(ntfs_mft_record));
  627.         if(!n)
  628.             return ENOMEM;
  629.         if(store->size){
  630.             for(i=0;i<store->size;i++)
  631.                 n[i]=store->records[i];
  632.             ntfs_free(store->records);
  633.         }
  634.         store->size=count+4;
  635.         store->records=n;
  636.     }
  637.     for(i=store->count;i<count;i++){
  638.         store->records[i].record=ntfs_malloc(vol->mft_recordsize);
  639.         if(!store->records[i].record)
  640.             return ENOMEM;
  641.         store->count++;
  642.     }
  643.     return 0;
  644. }
  645.  
  646. static void 
  647. deallocate_store(ntfs_disk_inode* store)
  648. {
  649.     int i;
  650.     for(i=0;i<store->count;i++)
  651.         ntfs_free(store->records[i].record);
  652.     ntfs_free(store->records);
  653.     store->count=store->size=0;
  654.     store->records=0;
  655. }
  656.  
  657. int 
  658. layout_runs(ntfs_attribute *attr,char* rec,int* offs,int size)
  659. {
  660.     int i,len,offset,coffs;
  661.     ntfs_cluster_t cluster,rclus;
  662.     ntfs_runlist *rl=attr->d.r.runlist;
  663.     cluster=0;
  664.     offset=*offs;
  665.     for(i=0;i<attr->d.r.len;i++){
  666.         rclus=rl[i].cluster-cluster;
  667.         len=rl[i].len;
  668.         rec[offset]=0;
  669.         if(offset+8>size)
  670.             return E2BIG; /* it might still fit, but this simplifies testing */
  671.         if(len<0x100){
  672.             NTFS_PUTU8(rec+offset+1,len);
  673.             coffs=1;
  674.         }else if(len<0x10000){
  675.             NTFS_PUTU16(rec+offset+1,len);
  676.             coffs=2;
  677.         }else if(len<0x1000000){
  678.             NTFS_PUTU24(rec+offset+1,len);
  679.             coffs=3;
  680.         }else{
  681.             NTFS_PUTU32(rec+offset+1,len);
  682.             coffs=4;
  683.         }
  684.     
  685.         *(rec+offset)|=coffs++;
  686.  
  687.         if(rl[i].cluster==MAX_CLUSTER_T) /*compressed run*/
  688.             /*nothing*/;
  689.         else if(rclus>-0x80 && rclus<0x7F){
  690.             *(rec+offset)|=0x10;
  691.             NTFS_PUTS8(rec+offset+coffs,rclus);
  692.             coffs+=1;
  693.         }else if(rclus>-0x8000 && rclus<0x7FFF){
  694.             *(rec+offset)|=0x20;
  695.             NTFS_PUTS16(rec+offset+coffs,rclus);
  696.             coffs+=2;
  697.         }else if(rclus>-0x800000 && rclus<0x7FFFFF){
  698.             *(rec+offset)|=0x30;
  699.             NTFS_PUTS24(rec+offset+coffs,rclus);
  700.             coffs+=3;
  701.         }else
  702. #if 0 /* In case ntfs_cluster_t ever becomes 64bit */
  703.         if (rclus>-0x80000000LL && rclus<0x7FFFFFFF)
  704. #endif
  705.         {
  706.             *(rec+offset)|=0x40;
  707.             NTFS_PUTS32(rec+offset+coffs,rclus);
  708.             coffs+=4;
  709.         }
  710. #if 0 /* For 64-bit ntfs_cluster_t */
  711.         else if (rclus>-0x8000000000 && rclus<0x7FFFFFFFFF){
  712.             *(rec+offset)|=0x50;
  713.             NTFS_PUTS40(rec+offset+coffs,rclus);
  714.             coffs+=5;
  715.         }else if (rclus>-0x800000000000 && rclus<0x7FFFFFFFFFFF){
  716.             *(rec+offset)|=0x60;
  717.             NTFS_PUTS48(rec+offset+coffs,rclus);
  718.             coffs+=6;
  719.         }else if (rclus>-0x80000000000000 && rclus<0x7FFFFFFFFFFFFF){
  720.             *(rec+offset)|=0x70;
  721.             NTFS_PUTS56(rec+offset+coffs,rclus);
  722.             coffs+=7;
  723.         }else{
  724.             *(rec+offset)|=0x80;
  725.             NTFS_PUTS64(rec+offset+coffs,rclus);
  726.             coffs+=8;
  727.         }
  728. #endif
  729.         offset+=coffs;
  730.         if(rl[i].cluster)
  731.             cluster=rl[i].cluster;
  732.     }
  733.     if(offset>=size)
  734.         return E2BIG;
  735.     /* terminating null */
  736.     *(rec+offset++)=0;
  737.     *offs=offset;
  738.     return 0;
  739. }
  740.  
  741. static void 
  742. count_runs(ntfs_attribute *attr,char *buf)
  743. {
  744.     ntfs_u32 first,count,last,i;
  745.     first=0;
  746.     for(i=0,count=0;i<attr->d.r.len;i++)
  747.         count+=attr->d.r.runlist[i].len;
  748.     last=first+count-1;
  749.  
  750.     NTFS_PUTU64(buf+0x10,first);
  751.     NTFS_PUTU64(buf+0x18,last);
  752.  
  753. static int
  754. layout_attr(ntfs_attribute* attr,char*buf, int size,int *psize)
  755. {
  756.     int asize,error;
  757.     if(size<10)return E2BIG;
  758.     NTFS_PUTU32(buf,attr->type);
  759.     /* fill in length later */
  760.     NTFS_PUTU8(buf+8,attr->resident ? 0:1);
  761.     NTFS_PUTU8(buf+9,attr->namelen);
  762.     /* fill in offset to name later */
  763.     NTFS_PUTU16(buf+0xA,0);
  764.     NTFS_PUTU16(buf+0xC,attr->compressed);
  765.     /* FIXME: assign attribute ID??? */
  766.     NTFS_PUTU16(buf+0xE,attr->attrno);
  767.     if(attr->resident){
  768.         if(size<attr->size+0x18+attr->namelen)return E2BIG;
  769.         asize=0x18;
  770.         NTFS_PUTU32(buf+0x10,attr->size);
  771.         NTFS_PUTU16(buf+0x16,attr->indexed);
  772.         if(attr->name){
  773.             ntfs_memcpy(buf+asize,attr->name,2*attr->namelen);
  774.             NTFS_PUTU16(buf+0xA,asize);
  775.             asize+=2*attr->namelen;
  776.             asize=(asize+7) & ~7;
  777.         }
  778.         NTFS_PUTU16(buf+0x14,asize);
  779.         ntfs_memcpy(buf+asize,attr->d.data,attr->size);
  780.         asize+=attr->size;
  781.     }else{
  782.         /* FIXME: fragments */
  783.         count_runs(attr,buf);
  784.         /* offset to data is added later */
  785.         NTFS_PUTU16(buf+0x22,attr->cengine);
  786.         NTFS_PUTU32(buf+0x24,0);
  787.         NTFS_PUTU64(buf+0x28,attr->allocated);
  788.         NTFS_PUTU64(buf+0x30,attr->size);
  789.         NTFS_PUTU64(buf+0x38,attr->initialized);
  790.         if(attr->compressed){
  791.             NTFS_PUTU64(buf+0x40,attr->compsize);
  792.             asize=0x48;
  793.         }else
  794.             asize=0x40;
  795.         if(attr->name){
  796.             NTFS_PUTU16(buf+0xA,asize);
  797.             ntfs_memcpy(buf+asize,attr->name,2*attr->namelen);
  798.             asize+=2*attr->namelen;
  799.             /* SRD: you whaaa?
  800.             asize=(asize+7) & ~7;*/
  801.         }
  802.         /* asize points at the beginning of the data */
  803.         NTFS_PUTU16(buf+0x20,asize);
  804.         error=layout_runs(attr,buf,&asize,size);
  805.         /* now asize pointes at the end of the data */
  806.         if(error)
  807.             return error;
  808.     }
  809.     asize=(asize+7) & ~7;
  810.     NTFS_PUTU32(buf+4,asize);
  811.     *psize=asize;
  812.     return 0;
  813. }
  814.         
  815.         
  816.  
  817. /* Try to layout ino into store. Return 0 on success,
  818.    E2BIG if it does not fit, 
  819.    ENOMEM if memory allocation problem,
  820.    EOPNOTSUP if beyond our capabilities 
  821. */
  822. int 
  823. layout_inode(ntfs_inode *ino,ntfs_disk_inode *store)
  824. {
  825.     int offset,i;
  826.     ntfs_attribute *attr;
  827.     unsigned char *rec;
  828.     int size,psize;
  829.     int error;
  830.  
  831.     if(ino->record_count>1)
  832.     {
  833.         ntfs_error("layout_inode: attribute lists not supported\n");
  834.         return EOPNOTSUPP;
  835.     }
  836.     error=allocate_store(ino->vol,store,1);
  837.     if(error)
  838.         return error;
  839.     rec=store->records[0].record;
  840.     size=ino->vol->mft_recordsize;
  841.     store->records[0].recno=ino->records[0];
  842.     /* copy header */
  843.     offset=NTFS_GETU16(ino->attr+0x14);
  844.     ntfs_memcpy(rec,ino->attr,offset);
  845.     for(i=0;i<ino->attr_count;i++){
  846.         attr=ino->attrs+i;
  847.         error=layout_attr(attr,rec+offset,size-offset,&psize);
  848.         if(error)return error;
  849.         offset+=psize;
  850. #if 0
  851.         /* copy attribute header */
  852.         ntfs_memcpy(rec+offset,attr->header,
  853.                 min(sizeof(attr->header),size-offset)); /* consider overrun */
  854.         if(attr->namelen)
  855.             /* named attributes are added later */
  856.             return EOPNOTSUPP;
  857.         /* FIXME: assign attribute ID??? */
  858.         if(attr->resident){
  859.             asize=attr->size;
  860.             aoffset=NTFS_GETU16(rec+offset+0x14);
  861.             if(offset+aoffset+asize>size)
  862.                 return E2BIG;
  863.             ntfs_memcpy(rec+offset+aoffset,attr->d.data,asize);
  864.             next=offset+aoffset+asize;
  865.         }else{
  866.             count_runs(attr,rec+offset);
  867.             aoffset=NTFS_GETU16(rec+offset+0x20);
  868.             next=offset+aoffset;
  869.             error=layout_runs(attr,rec,&next,size);
  870.             if(error)
  871.                 return error;
  872.         }
  873.         /* SRD: umm..
  874.         next=(next+7) & ~7; */
  875.         /* is this setting the length? if so maybe we could get
  876.            away with rounding up so long as we set the length first..
  877.            ..except, is the length the only way to get to the next attr?
  878.          */
  879.         NTFS_PUTU16(rec+offset+4,next-offset);
  880.         offset=next;
  881. #endif
  882.     }
  883.     /* terminating attribute */
  884.     if(offset+8<size){
  885.         NTFS_PUTU32(rec+offset,0xFFFFFFFF);
  886.         offset+=4;
  887.         NTFS_PUTU32(rec+offset,0);
  888.         offset+=4;
  889.     }else
  890.         return E2BIG;
  891.     NTFS_PUTU32(rec+0x18,offset);
  892.     return 0;
  893. }
  894.   
  895. int ntfs_update_inode(ntfs_inode *ino)
  896. {
  897.     int error;
  898.     ntfs_disk_inode store;
  899.     ntfs_io io;
  900.     int i;
  901.  
  902.     store.count=store.size=0;
  903.     store.records=0;
  904.     error=layout_inode(ino,&store);
  905.     if(error==E2BIG){
  906.         error = ntfs_split_indexroot(ino);
  907.         if(!error)
  908.             error = layout_inode(ino,&store);
  909.     }
  910.     if(error == E2BIG){
  911.         error = ntfs_attr_allnonresident(ino);
  912.         if(!error)
  913.             error = layout_inode(ino,&store);
  914.     }
  915.     if(error == E2BIG){
  916.         /* should try:
  917.            introduce extension records
  918.            */
  919.         ntfs_error("cannot handle saving inode %x\n",ino->i_number);
  920.         deallocate_store(&store);
  921.         return EOPNOTSUPP;
  922.     }
  923.     if(error){
  924.         deallocate_store(&store);
  925.         return error;
  926.     }
  927.     io.fn_get=ntfs_get;
  928.     io.fn_put=0;
  929.     for(i=0;i<store.count;i++){
  930.         ntfs_insert_fixups(store.records[i].record,ino->vol->blocksize);
  931.         io.param=store.records[i].record;
  932.         io.size=ino->vol->mft_recordsize;
  933.         /* FIXME: is this the right way? */
  934.         error=ntfs_write_attr(
  935.             ino->vol->mft_ino,ino->vol->at_data,0,
  936.             store.records[i].recno*ino->vol->mft_recordsize,&io);
  937.         if(error || io.size!=ino->vol->mft_recordsize){
  938.             /* big trouble, partially written file */
  939.             ntfs_error("Please unmount: write error in inode %x\n",ino->i_number);
  940.             deallocate_store(&store);
  941.             return error?error:EIO;
  942.         }
  943.     }
  944.     return 0;
  945. }       
  946.  
  947.  
  948. void ntfs_decompress(unsigned char *dest, unsigned char *src, ntfs_size_t l)
  949. {
  950.     int head,comp;
  951.     int copied=0;
  952.     unsigned char *stop;
  953.     int bits;
  954.     int tag=0;
  955.     int clear_pos;
  956.     while(1)
  957.     {
  958.         head = NTFS_GETU16(src) & 0xFFF;
  959.         /* high bit indicates that compression was performed */
  960.         comp = NTFS_GETU16(src) & 0x8000;
  961.         src += 2;
  962.         stop = src+head;
  963.         bits = 0;
  964.         clear_pos=0;
  965.         if(head==0)
  966.             /* block is not used */
  967.             return;/* FIXME: copied */
  968.         if(!comp) /* uncompressible */
  969.         {
  970.             ntfs_memcpy(dest,src,0x1000);
  971.             dest+=0x1000;
  972.             copied+=0x1000;
  973.             src+=0x1000;
  974.             if(l==copied)
  975.                 return;
  976.             continue;
  977.         }
  978.         while(src<=stop)
  979.         {
  980.             if(clear_pos>4096)
  981.             {
  982.                 ntfs_error("Error 1 in decompress\n");
  983.                 return;
  984.             }
  985.             if(!bits){
  986.                 tag=NTFS_GETU8(src);
  987.                 bits=8;
  988.                 src++;
  989.                 if(src>stop)
  990.                     break;
  991.             }
  992.             if(tag & 1){
  993.                 int i,len,delta,code,lmask,dshift;
  994.                 code = NTFS_GETU16(src);
  995.                 src+=2;
  996.                 if(!clear_pos)
  997.                 {
  998.                     ntfs_error("Error 2 in decompress\n");
  999.                     return;
  1000.                 }
  1001.                 for(i=clear_pos-1,lmask=0xFFF,dshift=12;i>=0x10;i>>=1)
  1002.                 {
  1003.                     lmask >>= 1;
  1004.                     dshift--;
  1005.                 }
  1006.                 delta = code >> dshift;
  1007.                 len = (code & lmask) + 3;
  1008.                 for(i=0; i<len; i++)
  1009.                 {
  1010.                     dest[clear_pos]=dest[clear_pos-delta-1];
  1011.                     clear_pos++;
  1012.                     copied++;
  1013.                     if(copied==l)
  1014.                         return;
  1015.                 }
  1016.             }else{
  1017.                 dest[clear_pos++]=NTFS_GETU8(src);
  1018.                 src++;
  1019.                 copied++;
  1020.                 if(copied==l)
  1021.                     return;
  1022.             }
  1023.             tag>>=1;
  1024.             bits--;
  1025.         }
  1026.         dest+=clear_pos;
  1027.     }
  1028. }
  1029.  
  1030. /* Caveat: No range checking in either ntfs_set_bit or ntfs_clear_bit */
  1031. void 
  1032. ntfs_set_bit (unsigned char *byte, int bit)
  1033. {
  1034.     byte += (bit >> 3);
  1035.     bit &= 7;
  1036.     *byte |= (1 << bit);
  1037. }
  1038.  
  1039. void 
  1040. ntfs_clear_bit (unsigned char *byte, int bit)
  1041. {
  1042.     byte += (bit >> 3);
  1043.     bit &= 7;
  1044.     *byte &= ~(1 << bit);
  1045. }
  1046.  
  1047. /* We have to skip the 16 metafiles and the 8 reserved entries */
  1048. static int 
  1049. new_inode (ntfs_volume* vol,int* result)
  1050. {
  1051.     int byte,error;
  1052.     int bit;
  1053.     int size,length;
  1054.     unsigned char value;
  1055.     ntfs_u8 *buffer;
  1056.     ntfs_io io;
  1057.     ntfs_attribute *data;
  1058.  
  1059.     buffer=ntfs_malloc(2048);
  1060.     if(!buffer)return ENOMEM;
  1061.     io.fn_put=ntfs_put;
  1062.     io.fn_get=ntfs_get;
  1063.     io.param=buffer;
  1064.     /* FIXME: bitmaps larger than 2048 bytes */
  1065.     io.size=2048;
  1066.     error=ntfs_read_attr(vol->mft_ino,vol->at_bitmap,0,0,&io);
  1067.     if(error){
  1068.         ntfs_free(buffer);
  1069.         return error;
  1070.     }
  1071.     size=io.size;
  1072.     data=ntfs_find_attr(vol->mft_ino,vol->at_data,0);
  1073.     length=data->size/vol->mft_recordsize;
  1074.  
  1075.     /* SRD: start at byte 0: bits for system files _are_ already set in bitmap */
  1076.     for (byte = 0; 8*byte < length; byte++)
  1077.     {
  1078.         value = buffer[byte];
  1079.         if(value==0xFF)
  1080.             continue;
  1081.         for (bit = 0; (bit < 8) && (8*byte+bit<length); 
  1082.              bit++, value >>= 1)
  1083.         {
  1084.             if (!(value & 1)){
  1085.                 *result=byte*8+bit;
  1086.                 return 0;
  1087.             }
  1088.         }
  1089.     }
  1090.     /* There is no free space.  We must first extend the MFT. */
  1091.     return ENOSPC;
  1092. }
  1093.  
  1094. static int 
  1095. add_mft_header (ntfs_inode *ino)
  1096. {
  1097.     unsigned char* mft;
  1098.     ntfs_volume *vol=ino->vol;
  1099.     mft=ino->attr;
  1100.  
  1101.     ntfs_bzero(mft, vol->mft_recordsize);
  1102.     ntfs_fill_mft_header(mft,vol->mft_recordsize,vol->blocksize,
  1103.             ino->sequence_number);
  1104.     return 0;
  1105. }
  1106.  
  1107. /* We need 0x48 bytes in total */
  1108. static int 
  1109. add_standard_information (ntfs_inode *ino)
  1110. {
  1111.     ntfs_time64_t now;
  1112.     char data[0x30];
  1113.     char *position=data;
  1114.     int error;
  1115.     ntfs_attribute *si;
  1116.  
  1117.     now = ntfs_now();
  1118.     NTFS_PUTU64(position + 0x00, now);              /* File creation */
  1119.     NTFS_PUTU64(position + 0x08, now);              /* Last modification */
  1120.     NTFS_PUTU64(position + 0x10, now);              /* Last mod for MFT */
  1121.     NTFS_PUTU64(position + 0x18, now);              /* Last access */
  1122.  
  1123.     NTFS_PUTU64(position + 0x20, 0x00);             /* MSDOS file perms */
  1124.     NTFS_PUTU64(position + 0x28, 0);               /* unknown */
  1125.     error=ntfs_create_attr(ino,ino->vol->at_standard_information,0,
  1126.                    data,sizeof(data),&si);
  1127.  
  1128.     return error;
  1129. }
  1130.  
  1131. static int 
  1132. add_filename (ntfs_inode* ino, ntfs_inode* dir, 
  1133.           const unsigned char *filename, int length, ntfs_u32 flags)
  1134. {
  1135.     unsigned char   *position;
  1136.     unsigned int    size;
  1137.     ntfs_time64_t   now;
  1138.     int             count;
  1139.     int error;
  1140.     unsigned char* data;
  1141.     ntfs_attribute *fn;
  1142.  
  1143.     /* work out the size */
  1144.     size = 0x42 + 2 * length;
  1145.     data = ntfs_malloc(size);
  1146.     if( !data )
  1147.         return ENOMEM;
  1148.     ntfs_bzero(data,size);
  1149.  
  1150.     /* search for a position */
  1151.     position = data;
  1152.  
  1153.     NTFS_PUTINUM(position, dir);    /* Inode num of dir */
  1154.  
  1155.     now = ntfs_now();
  1156.     NTFS_PUTU64(position + 0x08, now);              /* File creation */
  1157.     NTFS_PUTU64(position + 0x10, now);              /* Last modification */
  1158.     NTFS_PUTU64(position + 0x18, now);              /* Last mod for MFT */
  1159.     NTFS_PUTU64(position + 0x20, now);              /* Last access */
  1160.  
  1161.     /* Don't know */
  1162.     NTFS_PUTU32(position+0x38, flags);
  1163.  
  1164.     NTFS_PUTU8(position + 0x40, length);          /* Filename length */
  1165.     NTFS_PUTU8(position + 0x41, 0x0);             /* only long name */
  1166.  
  1167.     position += 0x42;
  1168.     for (count = 0; count < length; count++)
  1169.     {
  1170.         NTFS_PUTU16(position + 2 * count, filename[count]);
  1171.     }
  1172.  
  1173.     error=ntfs_create_attr(ino,ino->vol->at_file_name,0,data,size,&fn);
  1174.     if(!error)
  1175.         error=ntfs_dir_add(dir,ino,fn);
  1176.     ntfs_free(data);
  1177.     return error;
  1178. }
  1179.  
  1180. int 
  1181. add_security (ntfs_inode* ino, ntfs_inode* dir)
  1182. {
  1183.     int error;
  1184.     char *buf;
  1185.     int size;
  1186.     ntfs_attribute* attr;
  1187.     ntfs_io io;
  1188.     ntfs_attribute *se;
  1189.  
  1190.     attr=ntfs_find_attr(dir,ino->vol->at_security_descriptor,0);
  1191.     if(!attr)
  1192.         return EOPNOTSUPP; /* need security in directory */
  1193.     size = attr->size;
  1194.     if(size>512)
  1195.         return EOPNOTSUPP;
  1196.     buf=ntfs_malloc(size);
  1197.     if(!buf)
  1198.         return ENOMEM;
  1199.     io.fn_get=ntfs_get;
  1200.     io.fn_put=ntfs_put;
  1201.     io.param=buf;
  1202.     io.size=size;
  1203.     error=ntfs_read_attr(dir,ino->vol->at_security_descriptor,0,0,&io);
  1204.     if(!error && io.size!=size)ntfs_error("wrong size in add_security");
  1205.     if(error){
  1206.         ntfs_free(buf);
  1207.         return error;
  1208.     }
  1209.     /* FIXME: consider ACL inheritance */
  1210.     error=ntfs_create_attr(ino,ino->vol->at_security_descriptor,
  1211.                    0,buf,size,&se);
  1212.     ntfs_free(buf);
  1213.     return error;
  1214. }
  1215.  
  1216. static int 
  1217. add_data (ntfs_inode* ino, unsigned char *data, int length)
  1218. {
  1219.     int error;
  1220.     ntfs_attribute *da;
  1221.     error=ntfs_create_attr(ino,ino->vol->at_data,0,data,length,&da);
  1222.     return error;
  1223. }
  1224.  
  1225. /* We _could_ use 'dir' to help optimise inode allocation */
  1226. int ntfs_alloc_inode (ntfs_inode *dir, ntfs_inode *result, 
  1227.               const char *filename, int namelen, ntfs_u32 flags)
  1228. {
  1229.     ntfs_io io;
  1230.     int error;
  1231.     ntfs_u8 buffer[2];
  1232.     ntfs_volume* vol=dir->vol;
  1233.     int byte,bit;
  1234.  
  1235.     error=new_inode (vol,&(result->i_number));
  1236.     if(error==ENOSPC){
  1237.         error=ntfs_extend_mft(vol);
  1238.         if(error)return error;
  1239.         error=new_inode(vol,&(result->i_number));
  1240.     }
  1241.     if(error){
  1242.         ntfs_error ("ntfs_get_empty_inode: no free inodes\n");
  1243.         return error;
  1244.     }
  1245.     byte=result->i_number/8;
  1246.     bit=result->i_number & 7;
  1247.  
  1248.     io.fn_put = ntfs_put;
  1249.     io.fn_get = ntfs_get;
  1250.     io.param = buffer;
  1251.     io.size=1;
  1252.     /* set a single bit */
  1253.     error=ntfs_read_attr(vol->mft_ino,vol->at_bitmap,0,byte,&io);
  1254.     if(error)return error;
  1255.     if(io.size!=1)
  1256.         return EIO;
  1257.     ntfs_set_bit (buffer, bit);
  1258.     io.param = buffer;
  1259.     io.size = 1;
  1260.     error = ntfs_write_attr (vol->mft_ino, vol->at_bitmap, 0, byte, &io);
  1261.     if(error)return error;
  1262.     if (io.size != 1)
  1263.         return EIO;
  1264.     /*FIXME: Should change MFT on disk
  1265.       error=ntfs_update_inode(vol->mft_ino);
  1266.       if(error)return error;
  1267.       */
  1268.     /* get the sequence number */
  1269.     io.param = buffer;
  1270.     io.size = 2;
  1271.     error = ntfs_read_attr(vol->mft_ino, vol->at_data, 0, 
  1272.                    result->i_number*vol->mft_recordsize+0x10,&io);
  1273.     if(error)
  1274.         return error;
  1275.     result->sequence_number=NTFS_GETU16(buffer)+1;
  1276.     result->vol=vol;
  1277.     result->attr=ntfs_malloc(vol->mft_recordsize);
  1278.     if( !result->attr )
  1279.         return ENOMEM;
  1280.     result->attr_count=0;
  1281.     result->attrs=0;
  1282.     result->record_count=1;
  1283.     result->records=ntfs_malloc(8*sizeof(int));
  1284.     if( !result->records ) {
  1285.         ntfs_free( result->attr );
  1286.         result->attr = 0;
  1287.         return ENOMEM;
  1288.     }
  1289.     result->records[0]=result->i_number;
  1290.     error=add_mft_header(result);
  1291.     if(error)
  1292.         return error;
  1293.     error=add_standard_information(result);
  1294.     if(error)
  1295.         return error;
  1296.     error=add_filename(result,dir,filename,namelen,flags);
  1297.     if(error)
  1298.         return error;
  1299.     error=add_security(result,dir);
  1300.     /*FIXME: check error */
  1301.     return 0;
  1302. }
  1303.  
  1304. int
  1305. ntfs_alloc_file(ntfs_inode *dir, ntfs_inode *result, char *filename,
  1306.         int namelen)
  1307. {
  1308.     int error = ntfs_alloc_inode(dir,result,filename,namelen,0);
  1309.     if(error)
  1310.         return error;
  1311.     error = add_data(result,0,0);
  1312.     return error;
  1313. }
  1314.  
  1315. /*
  1316.  * Local variables:
  1317.  * c-file-style: "linux"
  1318.  * End:
  1319.  */
  1320.